package com.aeoj.clientmanagement.controller;

import cn.hutool.jwt.JWTUtil;
import com.aeoj.clientmanagement.domain.room.RoomProblem;
import com.aeoj.clientmanagement.domain.room.dto.RoomJoinDTO;
import com.aeoj.clientmanagement.domain.response.R;
import com.aeoj.clientmanagement.domain.room.Room;
import com.aeoj.clientmanagement.domain.room.RoomUser;
import com.aeoj.clientmanagement.domain.room.dto.RoomQuestionAddDTO;
import com.aeoj.clientmanagement.domain.room.dto.RoomReviewDTO;
import com.aeoj.clientmanagement.domain.room.dto.RoomSearchDTO;
import com.aeoj.clientmanagement.domain.room.vo.ApplicationRecordVO;
import com.aeoj.clientmanagement.domain.room.vo.RoomVO;
import com.aeoj.clientmanagement.domain.user.vo.SysUserVO;
import com.aeoj.clientmanagement.enums.ResponseCodeEnum;
import com.aeoj.clientmanagement.enums.room.RoomJoinStatusEnum;
import com.aeoj.clientmanagement.enums.room.RoomQuestionStatusEnum;
import com.aeoj.clientmanagement.enums.room.RoomTypeEnum;
import com.aeoj.clientmanagement.enums.room.RoomUserRemoveDTO;
import com.aeoj.clientmanagement.exception.BusinessException;
import com.aeoj.clientmanagement.service.RoomProblemService;
import com.aeoj.clientmanagement.service.RoomService;
import com.aeoj.clientmanagement.service.RoomUserService;
import com.aeoj.clientmanagement.service.SysUserService;
import com.aeoj.clientmanagement.utils.user.UserUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * RoomController
 * author: ZSM
 * time: 2025-04-21 13:07
 */
@RestController
@RequestMapping("/client/room")
public class RoomController {
    @Resource
    private RoomService roomService;
    @Resource
    private RoomUserService roomUserService;
    @Resource
    private RoomProblemService roomProblemService;
    @Resource
    private SysUserService sysUserService;

    /**
     * 房间列表
     * @param roomDTO
     * @return
     */
    @GetMapping("list")
    public R list(RoomSearchDTO roomDTO) {
        Page<Room> page = new Page<>(roomDTO.getPageNum(), roomDTO.getPageSize());
        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("create_time");
        if (roomDTO.getRoomName() != null)
            queryWrapper.like("name", roomDTO.getRoomName());
        if (roomDTO.getTags() != null)
            queryWrapper.like("tags", roomDTO.getTags());

        IPage<Room> roomIPage = roomService.page(page, queryWrapper);
        List<Room> roomList = roomIPage.getRecords();
        List<RoomVO> roomVOList = new ArrayList<>();
        roomList.forEach(x -> {
            RoomVO roomVO = RoomVO.toRoomVO(x);
            roomVO.setCreateUser(sysUserService.getSysUserVOById(x.getCreateBy()));
            roomVOList.add(roomVO);
        });

        IPage<RoomVO> res = new Page<>();
        res.setRecords(roomVOList);
        res.setTotal(roomIPage.getTotal());
        res.setSize(roomIPage.getSize());
        res.setCurrent(roomIPage.getCurrent());

        return R.ok(res);
    }

    /**
     * 加入房间
     * @param roomJoinDTO
     * @param request
     * @return
     */
    @PostMapping("join")
    public R join(@RequestBody RoomJoinDTO roomJoinDTO, HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);
        if (roomJoinDTO.getRoomId() == null) {
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);
        }
        Room room = roomService.getById(roomJoinDTO.getRoomId());
        if (room == null) {
            throw new BusinessException(ResponseCodeEnum.INTERNAL_SERVER_ERROR);
        }
        if (RoomTypeEnum.isEncrypted(room.getType())) {
            if (StringUtils.isEmpty(roomJoinDTO.getPassword()))
                throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);
            if (!room.getPassword().equals(roomJoinDTO.getPassword()))
                return R.error(ResponseCodeEnum.BUSINESS_ERROR, "密码错误");
        }
        if (RoomTypeEnum.isPrivate(room.getType())) {
            return R.error(ResponseCodeEnum.BUSINESS_ERROR, "私人房间不允许加入");
        }
        RoomUser roomUser = RoomUser.builder()
                .roomId(roomJoinDTO.getRoomId())
                .applyRemark(roomJoinDTO.getJoinReason())
                .userId(loginUser.getUserId())
                .status(RoomJoinStatusEnum.PENDING.getCode())
                .build();
        boolean save = roomUserService.save(roomUser);
        if (save)
            return R.ok();
        return R.error(ResponseCodeEnum.BUSINESS_ERROR);
    }

    /**
     * 退出房间
     * @param roomId
     * @param request
     * @return
     */
    @PostMapping("quit/{id}")
    public R quit(@PathVariable(value = "id") Long roomId, HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);
        if (roomId == null)
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);

        QueryWrapper<RoomUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("room_id", roomId);
        queryWrapper.eq("user_id", loginUser.getUserId());
        boolean remove = roomUserService.remove(queryWrapper);

        if (remove)
            return R.ok();
        return R.error(ResponseCodeEnum.BUSINESS_ERROR);
    }

    /**
     * 我的房间
     * @param dto
     * @param request
     * @return
     */
    @GetMapping("list_my_room")
    public R listMyRoom(RoomSearchDTO dto, HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);
        Page<Room> page = new Page<>(dto.getPageNum(), dto.getPageSize());

        QueryWrapper<RoomUser> roomUserQueryWrapper = new QueryWrapper<>();
        roomUserQueryWrapper.eq("user_id", loginUser.getUserId());
        List<RoomUser> roomUserList = roomUserService.list(roomUserQueryWrapper);
        List<Long> roomIdList = roomUserList.stream().map(RoomUser::getRoomId).toList();

        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("create_time");
        queryWrapper.eq("create_by", loginUser.getUserId())
                .or()
                .in("id", roomIdList);
        if (dto.getRoomName() != null) {
            queryWrapper.like("name", dto.getRoomName());
        }
        if (dto.getTags() != null) {
            queryWrapper.like("tags", dto.getTags());
        }

        List<Room> list = roomService.list(page, queryWrapper);
        List<RoomVO> roomVOList = new ArrayList<>();
        list.forEach(x -> {
            RoomVO roomVO = RoomVO.toRoomVO(x);
            SysUserVO createUser = sysUserService.getSysUserVOById(x.getCreateBy());
            roomVO.setCreateUser(createUser);
            roomVOList.add(roomVO);
        });

        IPage<RoomVO> res = new Page<>();
        res.setRecords(roomVOList);
        res.setTotal(list.size());
        res.setSize(list.size());
        return R.ok(res);
    }

    /**
     * 申请记录
     * @param dto
     * @param request
     * @return
     */
    @GetMapping("list_apply_record")
    public R listApplyRecord(RoomSearchDTO dto, HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);
        Page<RoomUser> page = new Page<>(dto.getPageNum(), dto.getPageSize());

        List<Long> roomIdList = roomService.listRoomIdsByUserId(loginUser.getUserId());

        QueryWrapper<RoomUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("create_time");
        queryWrapper.in("room_id", roomIdList);

        Page<RoomUser> res = roomUserService.page(page, queryWrapper);

        return R.ok(res);
    }

    /**
     * 审批
     * @param dto
     * @param request
     * @return
     */
    @PostMapping("review")
    public R review(@RequestBody RoomReviewDTO dto, HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);
        Integer target = dto.getTarget();
        if (!RoomJoinStatusEnum.isValid(target)) {
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);
        }

        RoomUser roomUser = RoomUser.builder()
                .id(dto.getId())
                .userId(loginUser.getUserId())
                .status(target)
                .rejectRemark(dto.getRemark())
                .build();

        boolean b = roomUserService.updateById(roomUser);

        if (b)
            return R.ok();

        return R.error(ResponseCodeEnum.BUSINESS_ERROR);
    }

    /**
     * 添加题目
     * @param dto
     * @param request
     * @return
     */
    @PostMapping("question/add")
    public R addQuestion(@RequestBody RoomQuestionAddDTO dto, HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);
        Long roomId = dto.getRoomId();
        if (roomId == null || roomId <= 0)
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);

        checkIsMyRoom(roomId, loginUser.getUserId());

        Long[] questionIds = dto.getQuestionIds();
        if (questionIds == null || questionIds.length == 0)
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);

        List<RoomProblem> roomProblemList = new ArrayList<>();

        for (Long questionId : questionIds) {
            RoomProblem roomProblem = RoomProblem.builder()
                    .problemId(questionId)
                    .roomId(roomId)
                    .createBy(loginUser.getUserId())
                    .status(RoomQuestionStatusEnum.NORMAL.getCode())
                    .build();
            roomProblemList.add(roomProblem);
        }

        boolean b = roomProblemService.saveBatch(roomProblemList);
        if (b)
            return R.ok();
        return R.error(ResponseCodeEnum.BUSINESS_ERROR);
    }

    /**
     * 删除题目
     * @param dto
     * @param request
     * @return
     */
    @PostMapping("question/remove")
    public R removeQuestion(@RequestBody RoomQuestionAddDTO dto, HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);

        Long roomId = dto.getRoomId();
        if (roomId == null || roomId <= 0)
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);

        Long[] questionIds = dto.getQuestionIds();
        if (questionIds == null || questionIds.length == 0)
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);

        checkIsMyRoom(roomId, loginUser.getUserId());

        QueryWrapper<RoomProblem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("room_id", roomId);
        queryWrapper.in("problem_id", questionIds);

        boolean b = roomProblemService.remove(queryWrapper);
        if (b)
            return R.ok();
        return R.error(ResponseCodeEnum.BUSINESS_ERROR);
    }

    /**
     * 禁用题目
     * @param ids
     * @param request
     * @return
     */
    @PostMapping("question/disable")
    public R disableQuestion(@RequestBody List<Long> ids, HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);

        if (ids == null || ids.isEmpty())
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);

        int b = roomProblemService.updateQuestionStatusByIds(ids, RoomQuestionStatusEnum.DISABLED.getCode());
        if (b == ids.size())
            return R.ok();
        return R.error(ResponseCodeEnum.BUSINESS_ERROR);
    }

    /**
     * 检查是否是我的房间
     * @param roomId
     * @param userId
     */
    private void checkIsMyRoom(Long roomId, Long userId) {
        Room room = roomService.getById(roomId);
        if (!room.getCreateBy().equals(userId))
            throw new BusinessException(ResponseCodeEnum.PERMISSION_DENIED);
    }

    /**
     * 删除用户
     * @param dto
     * @param request
     * @return
     */
    @PostMapping("user/remove")
    public R removeUser(@RequestBody RoomUserRemoveDTO dto, HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);
        Long roomId = dto.getRoomId();
        if (roomId == null || roomId <= 0)
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);
        checkIsMyRoom(roomId, loginUser.getUserId());

        Long[] userIds = dto.getUserIds();
        if (userIds == null || userIds.length == 0)
            throw new BusinessException(ResponseCodeEnum.BAD_REQUEST);

        QueryWrapper<RoomUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("room_id", roomId);
        queryWrapper.in("user_id", userIds);

        boolean b = roomUserService.remove(queryWrapper);
        if (b)
            return R.ok();
        return R.error(ResponseCodeEnum.BUSINESS_ERROR);
    }

    @GetMapping("chat")
    public R chat(HttpServletRequest request) {
        SysUserVO loginUser = UserUtils.getLoginUser(request);

        Map<String, Object> map = new HashMap<>();
        map.put("userId", loginUser.getUserId());
        map.put("expire_time", System.currentTimeMillis() + 1000 * 60 * 60);

        String token = JWTUtil.createToken(map, loginUser.getUserId().toString().getBytes());
        return R.ok(token);
    }
}
